"""
工具函数模块
提供各种通用工具函数，辅助其他模块
包括时间处理、文件操作、验证等功能
"""
import os
import re
import shutil
import zipfile
from datetime import datetime, timedelta
import logging

import shutil
from datetime import datetime, timedelta

def validate_datetime(datetime_str):
    """验证日期时间字符串格式"""
    formats = [
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%d %H:%M',
        '%Y-%m-%d'
    ]
    
    for fmt in formats:
        try:
            datetime.strptime(datetime_str, fmt)
            return True
        except ValueError:
            continue
    
    return False

def validate_time_range(start_time, end_time):
    """验证时间范围是否有效"""
    try:
        start = parse_datetime(start_time)
        if end_time:
            end = parse_datetime(end_time)
            return end > start
        return True
    except ValueError:
        return False

def parse_datetime(dt_str):
    """解析日期时间字符串为datetime对象"""
    formats = [
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%d %H:%M',
        '%Y-%m-%d'
    ]
    
    for fmt in formats:
        try:
            return datetime.strptime(dt_str, fmt)
        except ValueError:
            continue
    
    raise ValueError(f"无法解析日期时间字符串: {dt_str}")

def format_datetime(dt, include_seconds=False):
    """格式化datetime对象为字符串"""
    if isinstance(dt, str):
        return dt
    
    if include_seconds:
        return dt.strftime('%Y-%m-%d %H:%M:%S')
    else:
        return dt.strftime('%Y-%m-%d %H:%M')

def format_file_size(size_bytes):
    """格式化文件大小为可读字符串"""
    if size_bytes == 0:
        return "0 B"
    
    size_names = ["B", "KB", "MB", "GB"]
    i = 0
    while size_bytes >= 1024 and i < len(size_names) - 1:
        size_bytes /= 1024.0
        i += 1
    
    return f"{size_bytes:.2f} {size_names[i]}"

def get_priority_text(priority):
    """将优先级数字转换为文本"""
    priority_map = {1: "低", 2: "中", 3: "高"}
    return priority_map.get(priority, "未知")

def get_priority_color(priority):
    """根据优先级返回颜色（用于GUI）"""
    color_map = {
        1: "#90EE90",  # 低 - 浅绿色
        2: "#FFD700",  # 中 - 金色
        3: "#FFB6C1"   # 高 - 浅红色
    }
    return color_map.get(priority, "#FFFFFF")

def parse_natural_time(text, base_time=None):
    """
    解析自然语言时间（简化版）
    例如：1小时后，明天，下周一等
    """
    if base_time is None:
        base_time = datetime.now()
    
    text = text.lower().strip()
    
    # 相对时间解析
    time_patterns = {
        r"(\d+)\s*小时后": lambda m: base_time + timedelta(hours=int(m.group(1))),
        r"(\d+)\s*分钟后": lambda m: base_time + timedelta(minutes=int(m.group(1))),
        r"(\d+)\s*天后": lambda m: base_time + timedelta(days=int(m.group(1))),
        "现在": lambda m: base_time,
        "今天": lambda m: base_time.replace(hour=9, minute=0, second=0),
        "明天": lambda m: base_time + timedelta(days=1),
        "后天": lambda m: base_time + timedelta(days=2),
    }
    
    for pattern, converter in time_patterns.items():
        match = re.match(pattern, text)
        if match:
            return converter(match)
    
    return None

def validate_schedule_data(title, start_time, end_time=None, reminder_minutes=15):
    """验证日程数据有效性"""
    errors = []
    
    # 验证标题
    if not title or not title.strip():
        errors.append("日程标题不能为空")
    elif len(title.strip()) > 100:
        errors.append("日程标题不能超过100个字符")
    
    # 验证开始时间
    if not start_time or not start_time.strip():
        errors.append("开始时间不能为空")
    elif not validate_datetime(start_time):
        errors.append("开始时间格式不正确，请使用 YYYY-MM-DD HH:MM 格式")
    
    # 验证结束时间
    if end_time and end_time.strip():
        if not validate_datetime(end_time):
            errors.append("结束时间格式不正确，请使用 YYYY-MM-DD HH:MM 格式")
        elif not validate_time_range(start_time, end_time):
            errors.append("结束时间必须晚于开始时间")
    
    # 验证提醒时间
    if not isinstance(reminder_minutes, int) or reminder_minutes < 0 or reminder_minutes > 1440:
        errors.append("提醒时间必须在0-1440分钟之间")
    
    return errors

def backup_database(db_path):
    """备份数据库文件"""
    try:
        if not os.path.exists(db_path):
            logging.getLogger(__name__).warning(f"数据库文件不存在: {db_path}")
            return False
        
        backup_dir = "data/backups"
        os.makedirs(backup_dir, exist_ok=True)
        
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_name = f"schedules_backup_{timestamp}.db"
        backup_path = os.path.join(backup_dir, backup_name)
        
        shutil.copy2(db_path, backup_path)
        
        logging.getLogger(__name__).info(f"数据库已备份: {backup_path}")
        return backup_path
        
    except Exception as e:
        logging.getLogger(__name__).error(f"数据库备份失败: {e}")
        return False

def create_system_backup():
    """创建系统完整备份"""
    try:
        backup_dir = "data/backups"
        os.makedirs(backup_dir, exist_ok=True)
        
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_path = os.path.join(backup_dir, f"system_backup_{timestamp}.zip")
        
        with zipfile.ZipFile(backup_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 备份数据库
            if os.path.exists("data/schedules.db"):
                zipf.write("data/schedules.db", "schedules.db")
            
            # 备份配置文件
            if os.path.exists("config.json"):
                zipf.write("config.json", "config.json")
            
            # 备份最近的日志文件
            log_files = []
            if os.path.exists("data/logs"):
                for file in os.listdir("data/logs"):
                    if file.endswith(".log"):
                        log_files.append(os.path.join("data/logs", file))
                
                if log_files:
                    # 只备份最近的3个日志文件
                    log_files.sort(key=os.path.getmtime, reverse=True)
                    for log_file in log_files[:3]:
                        zipf.write(log_file, f"logs/{os.path.basename(log_file)}")
        
        logging.getLogger(__name__).info(f"系统备份已创建: {backup_path}")
        return backup_path
        
    except Exception as e:
        logging.getLogger(__name__).error(f"创建系统备份失败: {e}")
        return None

def cleanup_old_data(days=30):
    """清理旧的日志和备份文件"""
    try:
        cutoff_date = datetime.now() - timedelta(days=days)
        cleaned_count = 0
        
        # 清理旧日志
        log_dir = "data/logs"
        if os.path.exists(log_dir):
            for filename in os.listdir(log_dir):
                if filename.endswith(".log"):
                    file_path = os.path.join(log_dir, filename)
                    file_time = datetime.fromtimestamp(os.path.getmtime(file_path))
                    if file_time < cutoff_date:
                        os.remove(file_path)
                        cleaned_count += 1
                        logging.getLogger(__name__).info(f"删除旧日志文件: {filename}")
        
        # 清理旧备份（保留最近10个）
        backup_dir = "data/backups"
        if os.path.exists(backup_dir):
            backups = []
            for filename in os.listdir(backup_dir):
                if filename.startswith(("schedules_backup_", "system_backup_")):
                    file_path = os.path.join(backup_dir, filename)
                    if os.path.isfile(file_path):
                        backups.append((file_path, os.path.getmtime(file_path)))
            
            # 按修改时间排序，保留最近10个
            backups.sort(key=lambda x: x[1], reverse=True)
            for backup_path, _ in backups[10:]:
                os.remove(backup_path)
                cleaned_count += 1
                logging.getLogger(__name__).info(f"删除旧备份: {os.path.basename(backup_path)}")
        
        logging.getLogger(__name__).info(f"数据清理完成，共清理 {cleaned_count} 个文件")
        return cleaned_count
                
    except Exception as e:
        logging.getLogger(__name__).error(f"清理旧数据失败: {e}")
        return 0

def ensure_directory_structure():
    """确保项目目录结构完整"""
    directories = [
        "data",
        "data/exports",
        "data/logs", 
        "data/backups",
        "resources"
    ]
    
    for directory in directories:
        os.makedirs(directory, exist_ok=True)
    
    logging.getLogger(__name__).info("项目目录结构已确保完整")

# 测试函数
def test_utils():
    """测试工具函数"""
    print("测试工具函数...")
    
    # 测试时间验证
    assert validate_datetime("2024-01-01 10:30") == True
    assert validate_datetime("invalid-date") == False
    
    # 测试时间范围验证
    assert validate_time_range("2024-01-01 10:00", "2024-01-01 11:00") == True
    assert validate_time_range("2024-01-01 12:00", "2024-01-01 11:00") == False
    
    # 测试优先级转换
    assert get_priority_text(1) == "低"
    assert get_priority_text(2) == "中"
    assert get_priority_text(3) == "高"
    
    # 测试数据验证
    errors = validate_schedule_data("测试日程", "2024-01-01 10:00", "2024-01-01 09:00")
    assert "结束时间必须晚于开始时间" in errors
    
    errors = validate_schedule_data("", "2024-01-01 10:00")
    assert "日程标题不能为空" in errors
    
    print("所有工具函数测试通过!")

if __name__ == "__main__":
    # 配置日志
    logging.basicConfig(level=logging.INFO)
    
    # 测试工具函数
    test_utils()
    
    # 测试目录结构
    ensure_directory_structure()
    print("目录结构测试完成")